package com.qezhhnjy.bilibili.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.qezhhnjy.bilibili.entity.Payment;
import com.qezhhnjy.bilibili.mapper.PaymentMapper;
import com.qezhhnjy.bilibili.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.TimeUnit;

/**
 * @author zhaoyangfu - 2021/4/3 15:14
 */
@Service
@Slf4j
@DefaultProperties(defaultFallback = "globalFallback")
public class PaymentServiceImpl extends ServiceImpl<PaymentMapper, Payment>
        implements PaymentService {

    @Override
    public String paymentInfoOK(int id) {
        return "thread pool=>" + Thread.currentThread().getName() + " paymentInfo_OK, id=>" + id;
    }

    @HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandler"
            , commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
    })
    @Override
    public String paymentInfoTimeout(int id) throws Exception {
        log.error("paymentInfoTimeout method...");
        TimeUnit.SECONDS.sleep(3);
        // if (true) throw new Exception("11");
        return "thread pool=>" + Thread.currentThread().getName() + " paymentInfo_Timeout, id=>" + id;
    }

    public String paymentInfoTimeoutHandler(int id) {
        log.info("id=>{} 降级处理...", id);
        return "超时了，默认返回";
    }

    /**
     * 全局fallback
     */
    public String globalFallback() {
        return "服务端global fallback...";
    }

    @Override
    @Transactional
    public void testTransaction() throws Exception {
        Payment payment = new Payment(1L, "test transaction");
        updateById(payment);
        throw new Exception("aa");
    }

    // 服务熔断
    @HystrixCommand(
            fallbackMethod = "paymentCircuitBreakerFallback",
            commandProperties = {
                    // 是否开启断路器
                    @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
                    // 请求次数
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
                    // 时间窗日期
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
                    // 失败率达到多少后跳闸
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),
            }
    )
    @Override
    public String paymentCircuitBreaker(int id) {
        if (id < 0) {
            throw new RuntimeException("id 不能为负数");
        }
        return "paymentCircuitBreaker()调用成功...";
    }

    public String paymentCircuitBreakerFallback(int id) {
        return "id不能为负数，请稍后重试...";
    }
}
